package com.fowo.api.service.handleWork;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fowo.api.entity.*;
import com.fowo.api.mapper.*;
import com.fowo.api.model.funds.pay.order.FundsPayOrderVo;
import com.fowo.api.model.funds.pay.order.info.FundsPayOrderInfoItemVo;
import com.fowo.api.model.loan.monthly.balance.LoanMonthlyBalanceVo;
import com.fowo.api.model.loan.now.balance.LoanNowBalanceVo;
import com.fowo.api.model.purchase.order.PurchaseOrderVo;
import com.fowo.api.model.purchase.order.product.PurchaseOrderProductItemVo;
import com.fowo.api.service.FundsPayOrderService;
import com.fowo.api.service.LoanMonthlyBalanceService;
import com.fowo.api.service.LoanNowBalanceService;
import com.fowo.api.service.PurchaseOrderService;
import com.fowo.api.sys.annotation.DataActivity;
import com.fowo.api.sys.entity.enums.SysDataActivityAction;
import com.fowo.api.sys.model.NewSerialRequest;
import com.fowo.api.sys.service.SysSerialService;
import com.fowo.api.user.model.JwtUserInfo;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

@Service
public class FundsPayPoolServiceImpl implements FundsPayPoolService {

    @Resource
    private FundsPayOrderService fundsPayOrderService;
    @Resource
    private LoanNowBalanceMapper loanNowBalanceMapper;
    @Resource
    private LoanNowBalanceService loanNowBalanceService;
    @Resource
    private LoanMonthlyBalanceMapper loanMonthlyBalanceMapper;
    @Resource
    private LoanMonthlyBalanceService loanMonthlyBalanceService;
    @Resource
    private LoanAdvancePaymentMapper loanAdvancePaymentMapper;
    @Resource
    private LogisticsWithdrawMapper logisticsWithdrawMapper;
    @Resource
    private OtherPayablesMapper otherPayablesMapper;
    @Resource
    private PurchaseOrderService purchaseOrderService;
    @Resource
    protected SysSerialService sysSerialService;


    @DataActivity(
            action = SysDataActivityAction.Other,
            message = "%s执行了请款操作"
    )
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void requestPayout(FundsPayOrderVo param) throws Exception {
        Long id = fundsPayOrderService.getIdByAssociatedOrder(param.getAssociatedOrder());
        Assert.isNull(id,"该单据已请款，请勿重复操作！");
        JwtUserInfo currentUser = JwtUserInfo.fromHeader();
        if (currentUser != null) {
            param.setApplicant(currentUser.getUserId());
        }
        param.setApplyTime(new Date());
        param.setStatus("QK00");

        String payerType = "GYS";
        String feeName = "货值";
        switch (param.getCostType()){ //费用类型
            case "FY01":
                switch (param.getSettlementType()){ //结算方式
                    case "JS01":
                        updateLoanNowBalance(param);
                        break;
                    case "JS02":
                        updateLoanMonthlyBalance(param);
                        break;
                }
                break;
            case "FY03":
                feeName = "预付款";
                updateLoanAdvancePayment(param);
                break;
            case "FY02":
                payerType = "WLS";
                feeName = "物流费用";
                updateLogisticsWithdraw(param);
                break;
            case "FY04":
                feeName = "其他费用";
                updateOtherPayables(param);
                break;
        }
        param.setPayerType(payerType);
        BigDecimal amount = new BigDecimal(0.00);
        for(FundsPayOrderInfoItemVo itemVo : param.getInfoList()){
            itemVo.setFeeName(feeName);
            itemVo.setFeeMoney(itemVo.getThisApplication());
            amount = amount.add(itemVo.getThisApplication());
        }
        param.setPaymentAmount(amount);
        param.setUnpaidAmount(amount);
        param.setPaidAmount(new BigDecimal(0));
        fundsPayOrderService.create(param);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void batchRequestPayout(List<FundsPayOrderVo> params) throws Exception {
        for(FundsPayOrderVo model : params){
            requestPayout(model);
        }
    }

    /**
     * 更新贷款现结状态
     * @param param
     */
    public void updateLoanNowBalance(FundsPayOrderVo param) throws Exception {
        for(FundsPayOrderInfoItemVo itemVo : param.getInfoList()){
            LoanNowBalance loanNowBalance = loanNowBalanceMapper.selectOne(Wrappers.lambdaQuery(LoanNowBalance.class)
                    .eq(LoanNowBalance::getPurchaseOrderCode,itemVo.getPurchaseOrderCode())
            );

            LoanNowBalanceVo model = new LoanNowBalanceVo();
            BeanUtils.copyProperties(loanNowBalance, model);
            model.setStatus("20");
            model.setAmountPayable(itemVo.getAmountPayable());
            model.setInApplication(itemVo.getThisApplication());
            model.setNotApply(itemVo.getAmountPayable().subtract(itemVo.getThisApplication()));
            model.setDiscountAmount(itemVo.getThisDiscount());
            loanNowBalanceService.update(model);
        }
    }

    /**
     * 更新贷款月结
     * @param param
     */
    public void updateLoanMonthlyBalance(FundsPayOrderVo param) throws Exception {
        for(FundsPayOrderInfoItemVo itemVo : param.getInfoList()){
            LoanMonthlyBalance loanMonthlyBalance = loanMonthlyBalanceMapper.selectOne(Wrappers.lambdaQuery(LoanMonthlyBalance.class)
                    .eq(LoanMonthlyBalance::getPurchaseOrderCode,itemVo.getPurchaseOrderCode())
            );

            LoanMonthlyBalanceVo model = new LoanMonthlyBalanceVo();
            BeanUtils.copyProperties(loanMonthlyBalance, model);
            model.setQkSn(param.getOrderId());
            model.setStatus("20");
            model.setQkMoney(itemVo.getThisApplication());
            model.setNotApply(itemVo.getAmountPayable().subtract(itemVo.getThisApplication()));
            model.setDiscountAmount(itemVo.getThisDiscount());

            loanMonthlyBalanceService.update(model);

        }
    }

    /**
     * 更新贷款预付款
     * @param param
     */
    public void updateLoanAdvancePayment(FundsPayOrderVo param){
        FundsPayOrderInfoItemVo fundsPayOrderInfoItemVo = param.getInfoList().get(0);
        LoanAdvancePayment loanAdvancePayment = loanAdvancePaymentMapper.selectOne(Wrappers.lambdaQuery(LoanAdvancePayment.class)
                .eq(LoanAdvancePayment::getPurchaseOrderCode,fundsPayOrderInfoItemVo.getPurchaseOrderCode())
        );
        loanAdvancePayment.setStatus("20");
        loanAdvancePayment.setDiscountAmount(fundsPayOrderInfoItemVo.getThisDiscount());
        loanAdvancePayment.setInApplication(fundsPayOrderInfoItemVo.getThisApplication());
        loanAdvancePayment.setNotApply(fundsPayOrderInfoItemVo.getAmountPayable().subtract(fundsPayOrderInfoItemVo.getThisApplication()));
        loanAdvancePaymentMapper.updateById(loanAdvancePayment);
    }

    /**
     * 更新物流请款
     * @param param
     */
    public void updateLogisticsWithdraw(FundsPayOrderVo param){
        FundsPayOrderInfoItemVo fundsPayOrderInfoItemVo = param.getInfoList().get(0);
        LogisticsWithdraw logisticsWithdraw = logisticsWithdrawMapper.selectOne(Wrappers.lambdaQuery(LogisticsWithdraw.class)
                .eq(LogisticsWithdraw::getInoviceCode,fundsPayOrderInfoItemVo.getPurchaseOrderCode())
        );

        logisticsWithdraw.setStatus("20");
        logisticsWithdraw.setDiscountAmount(fundsPayOrderInfoItemVo.getThisDiscount());
        logisticsWithdraw.setInApplication(fundsPayOrderInfoItemVo.getThisApplication());
        logisticsWithdraw.setNotApply(fundsPayOrderInfoItemVo.getAmountPayable().subtract(fundsPayOrderInfoItemVo.getThisApplication()));
        logisticsWithdrawMapper.updateById(logisticsWithdraw);
    }

    /**
     * 更新其他应付款
     * @param param
     */
    public void updateOtherPayables(FundsPayOrderVo param){
        FundsPayOrderInfoItemVo fundsPayOrderInfoItemVo = param.getInfoList().get(0);
        OtherPayables otherPayables = otherPayablesMapper.selectOne(Wrappers.lambdaQuery(OtherPayables.class)
                .eq(OtherPayables::getFeeCode,fundsPayOrderInfoItemVo.getPurchaseOrderCode())
        );
        otherPayables.setStatus("20");
        otherPayables.setInApplication(fundsPayOrderInfoItemVo.getThisApplication());
        otherPayables.setNotApply(fundsPayOrderInfoItemVo.getAmountPayable().subtract(fundsPayOrderInfoItemVo.getThisApplication()));
        otherPayablesMapper.updateById(otherPayables);
    }

    /**
     * 添加预付款
     * @param purchaseId
     * @throws Exception
     */
    @Override
    public void insertLoanAdvancePayment(Long purchaseId) throws Exception{

        final PurchaseOrderVo purchaseOrderVo = purchaseOrderService.getVoById(purchaseId);
        if(!purchaseOrderVo.getSettlementMethod().equals("JS02")){
            return;
        }
        if(purchaseOrderVo.getAdvanceRatio()== null //没有预付比例
                || purchaseOrderVo.getAdvanceRatio().compareTo(new BigDecimal(0)) < 1) //预付比例小于0
        {
            return;
        }
        LoanAdvancePayment entity = loanAdvancePaymentMapper.selectOne(Wrappers.lambdaQuery(LoanAdvancePayment.class)
                .eq(LoanAdvancePayment::getPurchaseOrderCode,purchaseOrderVo.getPurchaseOrderCode()));
        if(null != entity){
            throw new Exception("该订单已预付");
        }
        final List<PurchaseOrderProductItemVo> purchaseOrderProductList = purchaseOrderVo.getPurchaseOrde();

        LoanAdvancePayment loanAdvancePayment = new LoanAdvancePayment();
        loanAdvancePayment.setSupplierName(purchaseOrderVo.getSupplierId());
        loanAdvancePayment.setPurchaseOrderCode(purchaseOrderVo.getPurchaseOrderCode());
        loanAdvancePayment.setApplicationDep(purchaseOrderVo.getApplicationDep());
        // 填充序列号
        if (!StringUtils.hasText(loanAdvancePayment.getPrepayOrderCode())) {
            loanAdvancePayment.setPrepayOrderCode(
                    sysSerialService.getNewSerial(
                            new NewSerialRequest(null, "LoanAdvancePayment.prepayOrderCode")
                    )
            );
        }
        loanAdvancePayment.setCreateTime(new Date());
        loanAdvancePayment.setLastUpdateTime(new Date());
        JwtUserInfo currentUser = JwtUserInfo.fromHeader();
        if (currentUser != null) {
            loanAdvancePayment.setCreateUser(currentUser.getUserId());
            loanAdvancePayment.setLastUpdateUser(currentUser.getUserId());
        }
        loanAdvancePayment.setStatus("10");
        loanAdvancePayment.setPurchaseQuantity(new BigDecimal(purchaseOrderVo.getPurchaseQuantity()));
        BigDecimal purchaseValue = purchaseOrderProductList.stream().map(p -> p.getTotalPrice()).reduce(BigDecimal.ZERO,BigDecimal::add);
        loanAdvancePayment.setPurchaseValue(purchaseValue);
        loanAdvancePayment.setBudgetRatio(purchaseOrderVo.getAdvanceRatio());

        BigDecimal shouldPrepayValue = purchaseValue.multiply(purchaseOrderVo.getAdvanceRatio().divide(new BigDecimal(100.00)));
        loanAdvancePayment.setShouldPrepayValue(shouldPrepayValue);
        loanAdvancePayment.setActuallyPaid(new BigDecimal(0.00));
        loanAdvancePayment.setUnpaidMoney(shouldPrepayValue);
        loanAdvancePayment.setOptUid(purchaseOrderVo.getOptUid());
        loanAdvancePayment.setDescribe(purchaseOrderVo.getSettlementDescribe());
        loanAdvancePayment.setPayType(purchaseOrderVo.getPaymentMethod());
//        loanAdvancePayment.setUserName();
//        loanAdvancePayment.setBankOfDeposit();
//        loanAdvancePayment.setAccount();
        loanAdvancePayment.setCurrency(purchaseOrderVo.getPurchaseCurrency());
        loanAdvancePayment.setRemarks(purchaseOrderVo.getRemarks());
        loanAdvancePayment.setInApplication(new BigDecimal(0.00));
        loanAdvancePayment.setNotApply(shouldPrepayValue);

        loanAdvancePaymentMapper.insert(loanAdvancePayment);
    }
}
